#include "VStdAfx.h"
#include "KRenderStateD3D9.h"
#include "KRenderD3D9.h"

void KRasterizerStateD3D9::DeleteThis()
{
	g_RenderD3D9->RemoveRasterizerState(this);
	VDelete this;
}

void KSamplerStateD3D9::DeleteThis()
{
	g_RenderD3D9->RemoveSamplerState(this);
	VDelete this;
}

void KDepthStencilStateD3D9::DeleteThis()
{
	g_RenderD3D9->RemoveDepthStencilState(this);
	VDelete this;
}

void KBlendStateD3D9::DeleteThis()
{
	g_RenderD3D9->RemoveBlendState(this);
	VDelete this;
}


VRRasterizerState* KRenderD3D9::CreateRasterizerState(const VRRasterizerStateDesc& RasterizerStateDesc)
{
	KRasterizerStateD3D9* RasterizerState = FindRasterizerState(RasterizerStateDesc);
	if (!RasterizerState)
	{
		RasterizerState = VNew KRasterizerStateD3D9(RasterizerStateDesc);
		RasterizerState->FillMode = VenusToD3D(RasterizerStateDesc.FillMode);
		RasterizerState->CullMode = VenusToD3D(RasterizerStateDesc.CullMode);
		RasterizerState->DepthBias = RasterizerStateDesc.DepthBias;
		RasterizerState->SlopeScaleDepthBias = RasterizerStateDesc.SlopeScaleDepthBias;
		RasterizerState->AllowMSAA = RasterizerStateDesc.AllowMSAA;

		m_RasterizerStates.PushBack(RasterizerState);
	}
	
	RasterizerState->AddRef();
	return RasterizerState;
}

VRSamplerState* KRenderD3D9::CreateSamplerState(const VRSamplerStateDesc& SamplerStateDesc)
{
	KSamplerStateD3D9* SamplerState = FindSamplerState(SamplerStateDesc);
	if (!SamplerState)
	{
		SamplerState = VNew KSamplerStateD3D9(SamplerStateDesc);
		SamplerState->AddressU = VenusToD3D(SamplerStateDesc.AddressU);
		SamplerState->AddressV = VenusToD3D(SamplerStateDesc.AddressV);
		SamplerState->AddressW = VenusToD3D(SamplerStateDesc.AddressW);

		switch(SamplerStateDesc.Filter)
		{
		case VRSF_POINT:
			SamplerState->MinFilter = D3DTEXF_POINT;
			SamplerState->MagFilter	= D3DTEXF_POINT;
			SamplerState->MipFilter	= D3DTEXF_POINT;
			break;
		case VRSF_BILINEAR:
			SamplerState->MinFilter = D3DTEXF_LINEAR;
			SamplerState->MagFilter	= D3DTEXF_LINEAR;
			SamplerState->MipFilter	= D3DTEXF_POINT;
			break;
		case VRSF_TRILINEAR:
			SamplerState->MinFilter = D3DTEXF_LINEAR;
			SamplerState->MagFilter	= D3DTEXF_LINEAR;
			SamplerState->MipFilter	= D3DTEXF_LINEAR;
			break;
		case VRSF_ANISOTROPICPOINT:
			SamplerState->MinFilter = D3DTEXF_ANISOTROPIC;
			SamplerState->MagFilter	= D3DTEXF_LINEAR;
			SamplerState->MipFilter	= D3DTEXF_POINT;
			break;
		case VRSF_ANISOTROPICLINEAR:
			SamplerState->MinFilter = D3DTEXF_ANISOTROPIC;
			SamplerState->MagFilter	= D3DTEXF_LINEAR;
			SamplerState->MipFilter	= D3DTEXF_LINEAR;
			break;
		}

		m_SamplerStates.PushBack(SamplerState);
	}
	
	SamplerState->AddRef();
	return SamplerState;
}

VRDepthStencilState* KRenderD3D9::CreateDepthStencilState(const VRDepthStencilStateDesc& DepthStateDesc)
{
	KDepthStencilStateD3D9* DepthStencilState = FindDepthStencilState(DepthStateDesc);
	if (!DepthStencilState)
	{
		DepthStencilState = VNew KDepthStencilStateD3D9(DepthStateDesc);

		// depth
		DepthStencilState->ZEnable = DepthStateDesc.DepthWriteEnable || DepthStateDesc.DepthTest != VRCF_ALWAYS;
		DepthStencilState->ZWriteEnable = DepthStateDesc.DepthWriteEnable;
		DepthStencilState->ZFunc = VenusToD3D(DepthStateDesc.DepthTest);

		// stencil
		DepthStencilState->StencilEnable = DepthStateDesc.FrontFace.Enable || DepthStateDesc.BackFace.Enable;
		DepthStencilState->TwoSidedStencilMode = DepthStateDesc.BackFace.Enable;
		DepthStencilState->StencilFunc = VenusToD3D(DepthStateDesc.FrontFace.StencilFunc);
		DepthStencilState->StencilFail = VenusToD3D(DepthStateDesc.FrontFace.StencilFailOp);
		DepthStencilState->StencilZFail = VenusToD3D(DepthStateDesc.FrontFace.StencilDepthFailOp);
		DepthStencilState->StencilPass = VenusToD3D(DepthStateDesc.FrontFace.StencilPassOp);
		DepthStencilState->CCWStencilFunc = VenusToD3D(DepthStateDesc.BackFace.StencilFunc);
		DepthStencilState->CCWStencilFail = VenusToD3D(DepthStateDesc.BackFace.StencilFailOp);
		DepthStencilState->CCWStencilZFail = VenusToD3D(DepthStateDesc.BackFace.StencilDepthFailOp);
		DepthStencilState->CCWStencilPass = VenusToD3D(DepthStateDesc.BackFace.StencilPassOp);
		DepthStencilState->StencilReadMask = DepthStateDesc.StencilReadMask;
		DepthStencilState->StencilWriteMask = DepthStateDesc.StencilWriteMask;
		DepthStencilState->StencilRef = DepthStateDesc.StencilRef;

		m_DepthStencilStates.PushBack(DepthStencilState);
	}

	DepthStencilState->AddRef();
	return DepthStencilState;
}

VRBlendState* KRenderD3D9::CreateBlendState(const VRBlendStateDesc& BlendStateDesc)
{
	KBlendStateD3D9* BlendState = FindBlendState(BlendStateDesc);
	if (BlendState == NULL)
	{
		BlendState = VNew KBlendStateD3D9(BlendStateDesc);

		BlendState->bSeparateAlphaBlendEnable = BlendStateDesc.AlphaBlendOp != VRBO_ADD || BlendStateDesc.AlphaSrcFactor != VRBF_ONE || BlendStateDesc.AlphaDestFactor != VRBF_ZERO;

		BlendState->AlphaBlendEnable = 
			BlendStateDesc.ColorBlendOp != VRBO_ADD || BlendStateDesc.ColorSrcFactor != VRBF_ONE || BlendStateDesc.ColorDestFactor != VRBF_ZERO ||
			BlendState->bSeparateAlphaBlendEnable;
		
		// COLOR
		BlendState->ColorBlendOp = VenusToD3D(BlendStateDesc.ColorBlendOp);
		BlendState->ColorSrcFactor = VenusToD3D(BlendStateDesc.ColorSrcFactor);
		BlendState->ColorDestFactor = VenusToD3D(BlendStateDesc.ColorDestFactor);

		// Alpha
		BlendState->AlphaBlendOp = VenusToD3D(BlendStateDesc.AlphaBlendOp);
		BlendState->AlphaSrcFactor = VenusToD3D(BlendStateDesc.AlphaSrcFactor);
		BlendState->AlphaDestFactor = VenusToD3D(BlendStateDesc.AlphaDestFactor);

		// Alpha test
		BlendState->bAlphaTestEnable = BlendStateDesc.AlphaTest != VRCF_ALWAYS;
		BlendState->AlphaFunc = VenusToD3D(BlendStateDesc.AlphaTest);
		BlendState->AlphaRef = BlendStateDesc.AlphaRef;
		//BlendState->BlendFactor = Initializer.ConstantBlendColor.ToFColor(FALSE).DWColor();

		m_BlendStates.PushBack(BlendState);
	}
	return BlendState;
}

void KRenderD3D9::SetRasterizerState(const VRRasterizerState* _RasterizerState,float DepthSlopeBaise )
{
	const KRasterizerStateD3D9* RasterizerState = (const KRasterizerStateD3D9*)_RasterizerState;
	m_Device->SetRenderState(D3DRS_FILLMODE,RasterizerState->FillMode);
	m_Device->SetRenderState(D3DRS_CULLMODE,RasterizerState->CullMode);
	// Add the global depth bias
	//extern FLOAT GDepthBiasOffset;
	//m_Device->SetRenderState(D3DRS_DEPTHBIAS,FLOAT_TO_DWORD(RasterizerState->DepthBias /*+ GDepthBiasOffset*/));
	//m_Device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS,FLOAT_TO_DWORD(RasterizerState->SlopeScaleDepthBias));
	if (DepthSlopeBaise > 0.001f)
	{
		//m_Device->SetRenderState(D3DRS_DEPTHBIAS,FLOAT_TO_DWORD(0.1f));
	}else
	{
		//m_Device->SetRenderState(D3DRS_DEPTHBIAS,FLOAT_TO_DWORD(0.0f));
	}
	
	m_Device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS,FLOAT_TO_DWORD(DepthSlopeBaise));
}

void KRenderD3D9::SetSamplerState(int Index, const VRSamplerState* _SamplerState)
{
	const KSamplerStateD3D9* SamplerState = (const KSamplerStateD3D9*)_SamplerState;

	//m_Device->SetSamplerState(Index,D3DSAMP_SRGBTEXTURE,SamplerState->);
	m_Device->SetSamplerState(Index,D3DSAMP_MAGFILTER,SamplerState->MagFilter);
	m_Device->SetSamplerState(Index,D3DSAMP_MINFILTER,SamplerState->MinFilter);
	m_Device->SetSamplerState(Index,D3DSAMP_MIPFILTER,SamplerState->MipFilter);
	m_Device->SetSamplerState(Index,D3DSAMP_ADDRESSU,SamplerState->AddressU);
	m_Device->SetSamplerState(Index,D3DSAMP_ADDRESSV,SamplerState->AddressV);
	m_Device->SetSamplerState(Index,D3DSAMP_ADDRESSW,SamplerState->AddressW);
	m_Device->SetSamplerState(Index,D3DSAMP_MIPMAPLODBIAS,SamplerState->MipMapLODBias);
	//m_Device->SetSamplerState(Index,D3DSAMP_MAXMIPLEVEL,(LargestMip < 0.0f) ? 0 : appTrunc(LargestMip));
	m_Device->SetSamplerState(Index,D3DSAMP_BORDERCOLOR,SamplerState->BorderColor);
}

void KRenderD3D9::SetDepthStencilState(const VRDepthStencilState* _DepthStencilState)
{
	const KDepthStencilStateD3D9* DepthStencilState = (const KDepthStencilStateD3D9*)_DepthStencilState;

	m_Device->SetRenderState(D3DRS_ZENABLE,DepthStencilState->ZEnable);
	m_Device->SetRenderState(D3DRS_ZWRITEENABLE,DepthStencilState->ZWriteEnable);
	m_Device->SetRenderState(D3DRS_ZFUNC,DepthStencilState->ZFunc);

	//////////////////////////////////////////////////////////////////////////
	// Stencil
	m_Device->SetRenderState(D3DRS_STENCILENABLE,DepthStencilState->StencilEnable);
	if (DepthStencilState->StencilEnable)
	{
		m_Device->SetRenderState(D3DRS_STENCILFUNC,DepthStencilState->StencilFunc);
		m_Device->SetRenderState(D3DRS_STENCILFAIL,DepthStencilState->StencilFail);
		m_Device->SetRenderState(D3DRS_STENCILZFAIL,DepthStencilState->StencilZFail);
		m_Device->SetRenderState(D3DRS_STENCILPASS,DepthStencilState->StencilPass);
		m_Device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE,DepthStencilState->TwoSidedStencilMode);
		m_Device->SetRenderState(D3DRS_CCW_STENCILFUNC,DepthStencilState->CCWStencilFunc);
		m_Device->SetRenderState(D3DRS_CCW_STENCILFAIL,DepthStencilState->CCWStencilFail);
		m_Device->SetRenderState(D3DRS_CCW_STENCILZFAIL,DepthStencilState->CCWStencilZFail);
		m_Device->SetRenderState(D3DRS_CCW_STENCILPASS,DepthStencilState->CCWStencilPass);
		m_Device->SetRenderState(D3DRS_STENCILMASK,DepthStencilState->StencilReadMask);
		m_Device->SetRenderState(D3DRS_STENCILWRITEMASK,DepthStencilState->StencilWriteMask);
		m_Device->SetRenderState(D3DRS_STENCILREF,DepthStencilState->StencilRef);
	}
	
}

void KRenderD3D9::SetBlendState(const VRBlendState* _BlendState)
{
	const KBlendStateD3D9* BlendState = (const KBlendStateD3D9*)_BlendState;
	m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE,BlendState->AlphaBlendEnable);
	m_Device->SetRenderState(D3DRS_BLENDOP,BlendState->ColorBlendOp);
	m_Device->SetRenderState(D3DRS_SRCBLEND,BlendState->ColorSrcFactor);
	m_Device->SetRenderState(D3DRS_DESTBLEND,BlendState->ColorDestFactor);

	m_Device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE,BlendState->bSeparateAlphaBlendEnable);
	m_Device->SetRenderState(D3DRS_BLENDOPALPHA,BlendState->AlphaBlendOp);
	m_Device->SetRenderState(D3DRS_SRCBLENDALPHA,BlendState->AlphaSrcFactor);
	m_Device->SetRenderState(D3DRS_DESTBLENDALPHA,BlendState->AlphaDestFactor);

	m_Device->SetRenderState(D3DRS_ALPHATESTENABLE,BlendState->bAlphaTestEnable);
	m_Device->SetRenderState(D3DRS_ALPHAFUNC,BlendState->AlphaFunc);
	m_Device->SetRenderState(D3DRS_ALPHAREF,BlendState->AlphaRef);
	m_Device->SetRenderState(D3DRS_BLENDFACTOR,BlendState->BlendFactor);
}


void KRenderD3D9::SetTexture(int Unit, VRTexture* Texture, VRSamplerState* SamplerState)
{
	VASSERT(m_Device);
	KRTextureD3D9* D3DTexture = (KRTextureD3D9*)Texture;
	if (D3DTexture)
	{
		m_Device->SetTexture(Unit, D3DTexture->m_Texture);
	}else
	{
		m_Device->SetTexture(Unit, NULL);
	}
	
}

